<?php

    class DatabaseException extends Exception {}

    class DBConnection extends mysqli
    {
        private static $instance;

        public function __construct($hostname = null, $username = null, $password = null, $port = null)
        {
            $config   = new ConfigParser(CONFIG_ROOT . "/config.cfg");
            
            if (is_null($hostname))
                $hostname = $config->hostname;
            if (is_null($username))
                $username = $config->username;
            if (is_null($password))
                $password = $config->password;
            if (is_null($port))
                $port     = $config->port;
            
            parent::__construct($hostname, $username, $password, "webauth", $port);
        }

        public function __destruct()
        {
            $this->close();
        }

        /**
         * Return a single instance of this object. If we don't currently have one,
         * create a singleton adn sreturn it.
         * @return DBConnection
         */
		public static function inst() {
			if(!isset(self::$instance)) {
				$class = __CLASS__;
				self::$instance = new $class;
			}
			return self::$instance;
		}

		/**
		 * Executes a stored procedure query. (Technically capable of any query,
		 * but this has additional logic to ensure that sprocs return all results.
         *
         * @param string $procedure The procedure in the database to execute
		 * @param array $params Any additional parameters (in order) to be passed to the routine
		 * @param array $returnData Reference to variable to store results;
		 * @return int return result of procedure;
		 */
		public function executeStoredProcedure($procedure,$params,&$returnData) {
			$returnVal = 0;
			$realParams = Array('@r'); //Set first parameter to always be the return value;

			if (is_array($params)) {
				foreach ($params as $p) {
					if (is_string($p) && $p != 'NULL') {
						$p = '\'' . $this->escape_string($p) . '\'';
						//echo $P;
					}
					if (!isset($p) || is_null($p)) {
						$p = 'NULL';
					}

                    if (is_bool($p)) {
                        $p = (int)$p;
                    }
					$realParams[] = $p;
				}
			}
			else {
				if(is_string($params) && $params != 'NULL') {
					$params = '\'' . $this->escape_string($params) . '\'';
				}
				$realparams[] = $params;
			} //Go through the parameters listed, escape any strings,
			//print_r($RealParams);
			$realParams = implode(',',$realParams); //Create the final parameter string;
			//echo ($RealParams);
			$realQueryString = ("CALL $procedure ($realParams); SELECT @r AS _returnVal;");
			if ($this->multi_query($realQueryString)) { //If succesful go through results and fetch to ReturnData;
				$returnData = Array();
				do {
					if ($r = $this->use_result()) {
						while ($data = $r->fetch_assoc()) {
                            if (isset($data['_returnVal'])) {
                                $returnVal = $data['_returnVal']; 	//If this record is the return value of the stored procedure
                                                                    //store into ReturnVal and ignore the result set;
                            }
                            else {
                                $returnData[] = $data;				//Store the result;
                            }
                        }
                        if ($r instanceof mysqli_result) {
                            $r->free();								//And free the result
                        }
                    }
				} while($this->next_result()); //Fetch results as long as there are some to select (stored procedures)
            }
			else {
				throw new DatabaseException('Database error. MySQL reports: ' . $this->error); //We broke the database, good job
			}
			return $returnVal;
		}
    }

?>
